package com.mail.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.mail.common.DataResult;
import com.mail.dto.QuartzEmailDto;
import com.mail.dto.SendEmailDto;
import com.mail.enums.ResponseCode;
import com.mail.job.SendEmailJob;
import com.mail.mapper.EmailConfigMapper;
import com.mail.mapper.MailMapper;
import com.mail.pojo.EmailConfig;
import com.mail.pojo.Mail;
import com.mail.service.MailService;
import com.mail.service.QuartzJobService;
import com.mail.vo.QuartzJobsVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
@Slf4j
public class QuartzJobServiceImpl implements QuartzJobService {

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private SchedulerFactoryBean springScheduler;

    @Resource
    private EmailConfigMapper emailConfigMapper;

    @Resource
    private MailMapper mailMapper;

    @Resource
    private MailService mailService;



    @SneakyThrows
    @Override
    @Transactional
    public DataResult saveJob(QuartzEmailDto quartzEmailDto) {
        if(!StringUtils.isNotBlank(quartzEmailDto.getCron())||
                !StringUtils.isNotBlank(quartzEmailDto.getAccountEmail())
                ||!StringUtils.isNotBlank(quartzEmailDto.getTitle())
                ||!StringUtils.isNotBlank(quartzEmailDto.getContent())
                ||!StringUtils.isNotBlank(quartzEmailDto.getSendMailName())
                ||!StringUtils.isNotBlank(quartzEmailDto.getReceiveMailName())){
            return DataResult.error(ResponseCode.LONG_INTEGER_IS_NULL.getMsg());
        }
        if(quartzEmailDto.getUserId()==null||!StringUtils.isNotBlank(quartzEmailDto.getPersonOrTeam())||quartzEmailDto.getReceiveMail().length<0){
            return DataResult.error(ResponseCode.LONG_INTEGER_IS_NULL.getMsg());
        }

        EmailConfig emailConfig=emailConfigMapper.queryConfigByAccount(quartzEmailDto.getAccountEmail());
        if(emailConfig==null){
            return DataResult.error(ResponseCode.EMAIL_CONFIG_ACCOUNT_IS_NULL.getMsg());
        }
        SendEmailDto sendEmailDto=new SendEmailDto();
        sendEmailDto.setPort(emailConfig.getEmailPort());
        sendEmailDto.setSendMailPwd(emailConfig.getEmailKey());
        sendEmailDto.setSendSMTPHost(emailConfig.getSendHost());
        sendEmailDto.setContent(quartzEmailDto.getContent());
        sendEmailDto.setSendMail(quartzEmailDto.getAccountEmail());
        sendEmailDto.setTitle(quartzEmailDto.getTitle());
        sendEmailDto.setSendMailName(quartzEmailDto.getSendMailName());
        sendEmailDto.setReceiveMail(quartzEmailDto.getReceiveMail());
        sendEmailDto.setReceiveMailName(quartzEmailDto.getReceiveMailName());

        String[]receiveMails= quartzEmailDto.getReceiveMail();
        String stringMails=String.join(",",receiveMails);

        Mail mail = new Mail(quartzEmailDto.getUserId(), quartzEmailDto.getAccountEmail(), quartzEmailDto.getTitle(), quartzEmailDto.getContent(), quartzEmailDto.getCron(), stringMails, quartzEmailDto.getPersonOrTeam(), quartzEmailDto.getSendMailName(), quartzEmailDto.getReceiveMailName());
        if(!quartzEmailDto.getPersonOrTeam().equals("0")){
            mail.setTeamId(quartzEmailDto.getTeamId());
        }
        mailMapper.insert(mail);

        log.info("----{}----",mail.getId());

        JobDataMap jobDataMap=new JobDataMap();
        jobDataMap.put("email",sendEmailDto);

        JobDetail jobDetail = JobBuilder.newJob(SendEmailJob.class)
                .withIdentity(String.valueOf(mail.getId()), quartzEmailDto.getAccountEmail())
                .usingJobData(jobDataMap)
                .storeDurably()
                .build();

        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(String.valueOf(mail.getId()), quartzEmailDto.getAccountEmail())
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule(quartzEmailDto.getCron()))
                .build();

        scheduler.scheduleJob(jobDetail, cronTrigger);
        if (!scheduler.isShutdown()) {
            scheduler.start();
        }
        return DataResult.success();

    }

    @SneakyThrows
    @Override
    public void rescheduleJob(String jobName, String cron) {
        long id=Long.parseLong(jobName);
        String jobGroupName=mailMapper.queryAccountEmailById(id);
        mailMapper.updateCronById(cron,id);
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey)
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                .build();
        scheduler.rescheduleJob(triggerKey, cronTrigger);
    }

    @SneakyThrows
    @Override
    @Transactional
    public void pauseJob(String jobName) {
        long id=Long.parseLong(jobName);
        String jobGroupName=mailMapper.queryAccountEmailById(id);
        mailMapper.updateStatus("1",id);
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @SneakyThrows
    @Override
    @Transactional
    public void resumeJob(String jobName) {
        long id=Long.parseLong(jobName);
        String jobGroupName=mailMapper.queryAccountEmailById(id);
        mailMapper.updateStatus("0",id);
        scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @SneakyThrows
    @Override
    @Transactional
    public void deleteJob(String jobName) {
        long id=Long.parseLong(jobName);
        String jobGroupName=mailMapper.queryAccountEmailById(id);
        mailMapper.deleteById(id);
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
    }

    @SneakyThrows
    @Override
    public DataResult listJobsByGroupName(String groupName) {
        List<QuartzJobsVo> quartzJobsVoList = new ArrayList<>();
        try {
            //获取Scheduler
            Scheduler scheduler = springScheduler.getScheduler();
            //再获取Scheduler下的所有group
            List<String> triggerGroupNames = scheduler.getTriggerGroupNames();
//            for (String groupName : triggerGroupNames) {
                //组装group的匹配，为了模糊获取所有的triggerKey或者jobKey
                GroupMatcher groupMatcher = GroupMatcher.groupEquals(groupName);
                //获取所有的triggerKey
                Set<TriggerKey> triggerKeySet = scheduler.getTriggerKeys(groupMatcher);
                for (TriggerKey triggerKey : triggerKeySet) {
                    //通过triggerKey在scheduler中获取trigger对象
                    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                    //获取trigger拥有的Job
                    JobKey jobKey = trigger.getJobKey();
                    JobDetailImpl jobDetail = (JobDetailImpl) scheduler.getJobDetail(jobKey);
                    //组装页面需要显示的数据
                    QuartzJobsVo quartzJobsVo = new QuartzJobsVo();
                    quartzJobsVo.setGroupName(groupName);
                    quartzJobsVo.setJobDetailName(jobDetail.getName());
                    quartzJobsVo.setJobCronExpression(trigger.getCronExpression());
                    quartzJobsVo.setTimeZone(trigger.getTimeZone().getID());
                    quartzJobsVoList.add(quartzJobsVo);
                    long id=Long.parseLong(jobDetail.getName());
                    quartzJobsVo.setStatus(mailMapper.queryStatusById(id));
                }
//            }
        } catch (Exception e) {
            log.error("获取定时任务信息出错", e);
        }
        return DataResult.success(quartzJobsVoList);
    }

}

